%%
%% Automated testrobot
%%
%% Writes to results.txt
%%
-module(testbot).

-compile(export_all).

test() ->

    % Start test bed master
    test_bed_master:start(),    

    %
    % Test1 
    %
    % DB Nodes: 10
    % Slaves:   10
    % Queries Total: 10 000
    %
    perform_test(5 ,10,1000,"testbed/results/test.txt"),
    perform_test(10,10,1000,"testbed/results/test.txt"),
    perform_three_tests(5,10,1000,"testbed/results/test2.txt"),
    perform_three_tests(10,10,1000,"testbed/results/test2.txt"),
    test_bed_master:stop().

%% 13/5 => 20d chord. 200,400,600,800 slaves
night_run() ->
    test_bed_master:start(),
    test_slaves_queries_chord_night_edition(50, 1000000),
    test_slaves_queries_chord_night_edition(100, 1000000),    
    test_slaves_queries_chord_night_edition(200, 1000000),
    test_slaves_queries_chord_night_edition(400, 1000000),
    test_slaves_queries_chord_night_edition_eight(600, 1000000),
    test_slaves_queries_chord_night_edition_eight(800, 1000000),
    test_slaves_queries_chord_night_edition(5, 1000000),
    test_bed_master:stop().

new_night_run() ->
    test_bed_master:start(),
    test_slaves_queries_chord_night_edition(50, 1000000),
    test_slaves_queries_chord_night_edition(200, 1000000),
    test_slaves_queries_chord_night_edition_eight(600, 1000000),
    test_bed_master:stop().

    
test_first_nodes() ->
    test_bed_master:start(),
    perform_three_tests(1,5,200000,"1node5slaves.txt"),
    perform_three_tests(1,50,20000,"1node50slaves.txt"),
    perform_three_tests(4,800,1250,"4nodes800slaves.txt"),
    test_bed_master:stop().


clever_cat() ->
    test_bed_master:start(),
    perform_three_tests(250,600,1667,"250nodes600slaves30comps.txt"),
    perform_three_tests(300,600,1667,"250nodes600slaves30comps.txt"),
    test_bed_master:stop().
    


tiny_test(Slaves) ->
    test_slaves_queries(Slaves,1000),
    test_slaves_queries(Slaves,1000).

test_slaves_amount(Slaves) ->
    test_slaves_queries(Slaves, 1000000).

test_slaves_amount_chord(Slaves) ->
    test_slaves_queries_chord_night_edition(Slaves, 1000000).

test_slaves_queries(Slaves, Queries) ->
    master:stop_all(),
    QueriesPerSlave = Queries div Slaves,
    Date = lists:flatten(io_lib:format("~w-~w-~w_",erlang:tuple_to_list(date()))),
    Timestamp = lists:flatten(io_lib:format("~w-~w-~w-",erlang:tuple_to_list(time()))),
    FileName = "testbed/results/"++Date++Timestamp++"test_slaves_queries-"++
                erlang:integer_to_list(Slaves)++"slaves-"++
                erlang:integer_to_list(Queries)++"queries.txt",

    % Start test bed master
%    test_bed_master:start(),  

    io:fwrite("**************************************testing 1 node!\n"),
    %perform_three_tests(1,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 2 nodes!\n"),
    %perform_three_tests(2,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 4 nodes!\n"),
    %perform_three_tests(4,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 8 nodes!\n"),
    perform_three_tests(8,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 16 nodes!\n"),
    
    perform_three_tests(16,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 32 nodes!\n"),
    perform_three_tests(32,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 64 nodes!\n"),
 
   perform_three_tests(64,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 100 nodes!\n"),

    perform_three_tests(100,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 150 nodes!\n"),
    perform_three_tests(150,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 200 nodes!\n"),

    perform_three_tests(200,Slaves,QueriesPerSlave,FileName),


    %perform_three_tests(250,Slaves,QueriesPerSlave,FileName),
    %perform_three_tests(300,Slaves,QueriesPerSlave,FileName),
    io:fwrite("DONE!!!!!!!!!!!!!\n"),

    io:fwrite("\n**********************TEST HAS FINISHED!**********************\n").
%    test_bed_master:stop().



test_slaves_queries_chord_night_edition(Slaves, Queries) ->
    master:stop_all(),
    QueriesPerSlave = Queries div Slaves,
    Date = lists:flatten(io_lib:format("~w-~w-~w_",erlang:tuple_to_list(date()))),
    Timestamp = lists:flatten(io_lib:format("~w-~w-~w-",erlang:tuple_to_list(time()))),
    NumComps = length(nodes()) div 10,
    FileName = "testbed/results/"++Date++Timestamp++"test_slaves_queries-"++
                erlang:integer_to_list(Slaves)++"slaves-"++
                erlang:integer_to_list(Queries)++"queries"++
                integer_to_list(NumComps)++"computers"++"___CHORD",


    write_to_file(integer_to_list(NumComps)++" datorer\n\n",[],FileName),

    io:fwrite("**************************************testing 1 node!\n"),
  %  perform_three_tests_chord(1,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 2 nodes!\n"),
   % perform_three_tests_chord(2,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 4 nodes!\n"),
    %perform_three_tests_chord(4,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 8 nodes!\n"),
    perform_three_tests_chord(8,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 16 nodes!\n"),
    
    perform_three_tests_chord(16,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 32 nodes!\n"),
    perform_three_tests_chord(32,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 64 nodes!\n"),
 
    perform_three_tests_chord(64,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 100 nodes!\n"),

    perform_three_tests_chord(100,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 150 nodes!\n"),
    perform_three_tests_chord(150,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 200 nodes!\n"),

    perform_three_tests_chord(200,Slaves,QueriesPerSlave,FileName),


    %perform_three_tests(250,Slaves,QueriesPerSlave,FileName),
    %perform_three_tests(300,Slaves,QueriesPerSlave,FileName),
    io:fwrite("DONE!!!!!!!!!!!!!\n"),

    io:fwrite("\n**********************TEST HAS FINISHED!**********************\n").

test_slaves_queries_chord_night_edition_eight(Slaves, Queries) ->
    master:stop_all(),
    QueriesPerSlave = Queries div Slaves,
    Date = lists:flatten(io_lib:format("~w-~w-~w_",erlang:tuple_to_list(date()))),
    Timestamp = lists:flatten(io_lib:format("~w-~w-~w-",erlang:tuple_to_list(time()))),
    NumComps = length(nodes()) div 10,
    FileName = "testbed/results/"++Date++Timestamp++"test_slaves_queries-"++
                erlang:integer_to_list(Slaves)++"slaves-"++
                erlang:integer_to_list(Queries)++"queries"++
                integer_to_list(NumComps)++"computers"++"___CHORD",


    write_to_file(integer_to_list(NumComps)++" datorer\n\n",[],FileName),

    %io:fwrite("**************************************testing 4 nodes!\n"),
    %perform_three_tests(4,Slaves,QueriesPerSlave,FileName),

    %io:fwrite("**************************************testing 8 nodes!\n"),
    perform_three_tests_chord(8,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 16 nodes!\n"),
    
    perform_three_tests_chord(16,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 32 nodes!\n"),
    perform_three_tests_chord(32,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 64 nodes!\n"),
 
   perform_three_tests_chord(64,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 100 nodes!\n"),

    perform_three_tests_chord(100,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 150 nodes!\n"),
    perform_three_tests_chord(150,Slaves,QueriesPerSlave,FileName),

    io:fwrite("**************************************testing 200 nodes!\n"),

    perform_three_tests_chord(200,Slaves,QueriesPerSlave,FileName),


    %perform_three_tests(250,Slaves,QueriesPerSlave,FileName),
    %perform_three_tests(300,Slaves,QueriesPerSlave,FileName),
    io:fwrite("DONE!!!!!!!!!!!!!\n"),

    io:fwrite("\n**********************TEST HAS FINISHED!**********************\n").



%% Executes a test and writes results to file
perform_test(DBNodes, Slaves, QueriesPerSlave, File) ->
    
    {Fmt, Params} = execute_test(DBNodes, Slaves, QueriesPerSlave),
    write_results(DBNodes, Slaves, QueriesPerSlave, Fmt,Params,File).


perform_three_tests(DBNodes, Slaves, QueriesPerSlave, File) ->
    
    {Fmt, Params} = execute_three_times_mesh(DBNodes, Slaves, QueriesPerSlave),
    write_results(DBNodes, Slaves, QueriesPerSlave, Fmt, Params, File).
    


perform_three_tests_chord(DBNodes, Slaves, QueriesPerSlave, File) ->
    
    {Fmt, Params} = execute_three_times_chord(DBNodes, Slaves, QueriesPerSlave),
    write_results(DBNodes, Slaves, QueriesPerSlave, Fmt, Params, File).
    

%% Execute a single test, returns {Formatted String, Params}
execute_test_chord(DBNodes, Slaves, QueriesPerSlave) ->
    master:start_test_chord_delay(DBNodes),
    test_bed_master:start_slaves(Slaves),
    test_bed_master:setf_db2([QueriesPerSlave]),
    {Fmt,Param} = test_bed_master:run_tests(),
    test_bed_master:kill_all(),
    {Format,Params} = check_distribution:run_test(),
    master:stop_all(),

    {Fmt++Format, Param ++ Params}.


%% Execute a single test, returns {Formatted String, Params}
execute_test(DBNodes, Slaves, QueriesPerSlave) ->
    master:start_test_mesh(DBNodes),
    test_bed_master:start_slaves(Slaves),
    test_bed_master:setf_db2([QueriesPerSlave]),
    {Fmt,Param} = test_bed_master:run_tests(),
    test_bed_master:kill_all(),
    {Format,Params} = check_distribution:run_test(),
    master:stop_all(),

    {Fmt++Format, Param ++ Params}.
    

%% Execute a test three times, returns {Formatted String, Average Params}
execute_three_times_mesh(DBN, S, QPS) ->
    {Fmt,Param1} = execute_test(DBN,S,QPS),
    {_,Param2} = execute_test(DBN,S,QPS),
    {_,Param3} = execute_test(DBN,S,QPS),
    Result = lists:zipwith3(fun(X,Y,Z)->(X+Y+Z)/3 end, Param1, Param2, Param3),
    {Fmt,Result}.

%% Execute a test three times, returns {Formatted String, Average Params}
execute_three_times_chord(DBN, S, QPS) ->
    {Fmt,Param1} = execute_test_chord(DBN,S,QPS),
    {_,Param2} = execute_test_chord(DBN,S,QPS),
    {_,Param3} = execute_test_chord(DBN,S,QPS),
    Result = lists:zipwith3(fun(X,Y,Z)->(X+Y+Z)/3 end, Param1, Param2, Param3),
    {Fmt,Result}.


write_results(DBNodes, Slaves, QueriesPerSlave, Fmt, Params, File) ->
    write_to_file("********************************************************~n",[], File),
    write_to_file("Starting test: DB Nodes: ~w, Slaves ~w, Queries/Slave ~w",
                    [DBNodes,Slaves,QueriesPerSlave], File),
    write_to_file(Fmt,Params, File),
    write_to_file("\nEnd test~n", [], File),
    write_to_file("********************************************************~n~n~n",
                 [], File).


write_to_file(Fmt,Params, File) ->
    {ok,Dev} = file:open(File,[append]),
    file:write(Dev,io_lib:format(Fmt,Params)),
    file:close(Dev).
